package com.huahai.manager.websocket.interceptor;

import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.huahai.manager.auth.SpaceUserAuthManager;
import com.huahai.manager.auth.constants.SpaceUserPermissionConstant;
import com.huahai.pojo.entity.Picture;
import com.huahai.pojo.entity.Space;
import com.huahai.pojo.entity.User;
import com.huahai.pojo.enums.SpaceTypeEnum;
import com.huahai.service.PictureService;
import com.huahai.service.SpaceService;
import com.huahai.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;

/**
 * WebSocket 握手拦截器 - 在发送请求前进行权限的校验
 *
 * @author huahai
 */
@Component
@Slf4j
public class WsHandShakeInterceptor implements HandshakeInterceptor {

    @Resource
    private PictureService pictureService;

    @Resource
    private UserService userService;

    @Resource
    private SpaceService spaceService;

    @Resource
    private SpaceUserAuthManager spaceUserAuthManager;

    /**
     * 在发送请求前进行权限的校验，返回 true 表示允许连接，返回 false 表示不允许连接
     * @param request HTTP请求对象，包含客户端发送的请求信息
     * @param response HTTP响应对象，用于向客户端返回响应信息
     * @param wsHandler WebSocket处理器，处理WebSocket连接的相关逻辑
     * @param attributes 用于存储 WebSocket会话属性的映射表
     * @return boolean 返回true表示握手成功，允许建立连接；返回false表示握手失败，拒绝连接
     * @throws Exception 当权限校验过程中发生异常时抛出
     */
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
        // 1. 获取请求参数
        if(request instanceof ServletServerHttpRequest){
            HttpServletRequest servletRequest = ((ServletServerHttpRequest) request).getServletRequest();
            // 2. 校验图片是否存在
            String pictureId = servletRequest.getParameter("pictureId");
            if(StrUtil.isBlank(pictureId)){
                log.error("缺少图片参数，拒绝握手");
                return false;
            }
            Picture picture = pictureService.getById(pictureId);
            if(picture == null){
                log.error("图片不存在，拒绝握手");
                return false;
            }
            // 3. 校验用户登录态
            User loginUser = userService.getLoginUser(servletRequest);
            if(ObjUtil.isEmpty(loginUser)){
                log.error("用户未登录，拒绝握手");
                return false;
            }
            // 4. 校验图片所在的空间
            Long spaceId = picture.getSpaceId();
            Space space = null;
            if(spaceId != null){
                // 判断空间是否存在
                space = spaceService.getById(spaceId);
                if(space == null){
                    log.error("空间不存在，拒绝握手");
                    return false;
                }
                // 判断是否为团队空间
                if(!space.getSpaceType().equals(SpaceTypeEnum.TEAM.getValue())){
                    log.error("不是团队空间，拒绝握手");
                    return false;
                }
            }
            // 5. 校验当前登录用户是否具有操作该图片的权限
            List<String> permissionList = spaceUserAuthManager.getPermissionList(space, loginUser);
            if(!permissionList.contains(SpaceUserPermissionConstant.PICTURE_EDIT)){
                log.error("用户没有编辑该图片的权限，拒接握手");
                return false;
            }
            // 6. 设置用户信息，用户 id，图片 id到 websocket session中
            attributes.put("userId", loginUser.getId());
            attributes.put("user", loginUser);
            // 将 pictureId 转换为 Long 类型 !!! 不然接收不到 pictureId
            attributes.put("pictureId", Long.valueOf(pictureId));
        }
        return true;
    }

    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {

    }
}
